package rever;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Creared with IntelliJ IDEA.
 * Description:反射 可以获取类中的方法属性的一种机制 最多使用在框架当中 反射相关的类 class类（类的实体） Field类（类的成员变量/类的属性）Method类（类的方法） Constructor类（类的构造方法）
 * 通过这些类来实现反射，使用反射会降低效率，平时一般不使用
 * User:yxd
 * Date:2022-03-01
 * Time:15:19
 */
class Student{
    private String name = "bit";
    public int age = 18;

    public Student() {
        System.out.println("student()");
    }
    //私有的
    private Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("name,age");
    }
    private void eat(){
        System.out.println("eat()");
    }
    public void sleep(){
        System.out.println("sleep()");
    }
    private void fun(String s){
        System.out.println(s);
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Reflex {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取Class类
        Class<?> c1 = Class.forName("Reflex.Student");//1.获取class对象
        Class<?> c2 = Student.class;//第2种
        Student student = new Student();
        Class<?> c3 = student.getClass();//第三种 这些取到的对象都是相等的，class对象只有一个 不管是用哪种方法，前两种使用最多


    }

//获取私有的对象
    public static void reflectNewInstance() {
        //反射的使用
        try {
            Class<?> c1 = Class.forName("Reflex.Student");
            Student student = (Student) c1.newInstance();//获取实例 现在就可以获取类中的属性方法
            System.out.println(student);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    //带参数的私有构造方法的反射
    public static void reflectPrivateConstructor() {
        try {
            Class<?> c1 = Class.forName("Reflex.Student");
            Constructor<?> constructor = c1.getDeclaredConstructor(String.class, int.class);//反射获取私有的构造方法，公有的也可以

            constructor.setAccessible(true);//将此构造方法不再私有 改成可以访问
            Student student = (Student) constructor.newInstance("y", 20);
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
//获取私有的属性
    public static void reflectPrivateField() {
        try {
            Class<?> c1 = Class.forName("Reflex.Student");
            Student student = (Student) c1.newInstance();//获取对象
            Field field = c1.getDeclaredField("name");//获取私有的属性
            field.setAccessible(true);//修改为可获得的
            field.set(student, "xx");//此时就修改了
            System.out.println(student);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
//获取私有的方法
    public static void reflectPrivateMethod() {
        try {
            Class<?> c1 = Class.forName("Reflex.Student");
            Student student = (Student) c1.newInstance();//获取对象
            Method method = c1.getDeclaredMethod("fun",String.class);
            method.setAccessible(true);
            method.invoke(student,"私有的方法参数");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
